package cmd

import (
	"os"
	"os/signal"
	"syscall"

	"network/v3/internal/gateway"
	"network/v3/internal/uplink"
	log "network/v3/pkg/logger"

	"github.com/spf13/cobra"
)

func run(*cobra.Command, []string) error {
	server := new(uplink.Server)

	runTasks(server)
	runListenSignal(server)

	return nil
}

func runTasks(server *uplink.Server) {
	tasks := []func() error{
		setLogLevel,
		setSyslog,
		setGRPCResolver,
		setupBand,
		setRXParameters,
		printStartMessage,
		enableUplinkChannels,
		setupStorage,
		setGatewayBackend,
		setupApplicationServer,
		setupADR,
		setupJoinServer,
		setupNetworkController,
		setupUplink,
		setupDownlink,
		setupNetworkServerAPI,
		setupGateways,
		startLoRaServer(server),
		startQueueScheduler,
	}

	for _, task := range tasks {
		if err := task(); err != nil {
			log.Fatal(err)
		}
	}
}

func runListenSignal(server *uplink.Server) {
	sigChan := make(chan os.Signal)
	exitChan := make(chan struct{})
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	log.WithField("signal", <-sigChan).Info("signal received")

	go func() {
		log.Warning("stopping chirpstack-network-server")
		if err := server.Stop(); err != nil {
			log.Fatal(err)
		}
		if err := gateway.Stop(); err != nil {
			log.Fatal(err)
		}
		exitChan <- struct{}{}
	}()

	select {
	case <-exitChan:
	case s := <-sigChan:
		log.WithField("signal", s).Info("signal received, stopping immediately")
	}
}
